<template>
  <a-tree-select v-bind="getAttrs" @change="handleChange">
    <template #[item]="data" v-for="item in Object.keys($slots)">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </a-tree-select>
</template>

<script setup lang="ts">
  import { isArray, isFunction } from '@/utils/is'
  import { propTypes } from '@/utils/propTypes'
  import { get } from 'lodash-es'
  import { computed, onMounted, ref, unref, watch } from 'vue'
  const props = defineProps({
    api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> },
    params: { type: Object },
    immediate: { type: Boolean, default: true },
    resultField: propTypes.string.def(''),
    refresh: { type: Boolean, default: false },
  })
  const emit = defineEmits(['options-change', 'change'])
  const attrs = useAttrs()
  const treeData = ref<Recordable[]>([])
  const isFirstLoaded = ref<boolean>(false)
  const loading = ref(false)
  const getAttrs = computed(() => {
    return {
      ...(props.api ? { treeData: unref(treeData) } : {}),
      ...attrs
    }
  })

  function handleChange(...args) {
    emit('change', ...args)
  }

    watch(
    () => props.refresh,
    () => {
      props.refresh && fetch()
    },
    { deep: true }
  )
  watch(
    () => props.params,
    () => {
      !unref(isFirstLoaded) && fetch()
    },
    { deep: true }
  )

  watch(
    () => props.immediate,
    (v) => {
      v && !isFirstLoaded.value && fetch()
    }
  )

  onMounted(() => {
    props.immediate && fetch()
  })

  async function fetch() {
    const { api } = props
    if (!api || !isFunction(api)) return
    loading.value = true
    treeData.value = []
    let result
    try {
      result = await api(props.params)
    } catch (e) {
      console.error(e)
    }
    loading.value = false
    if (!result) return
    if (!isArray(result)) {
      result = get(result, props.resultField)
    }
    treeData.value = (result as Recordable[]) || []
    isFirstLoaded.value = true
    emit('options-change', treeData.value)
  }
</script>
